import { io, type Socket } from "socket.io-client";
import type { DrawStroke, GameState, Player } from "../types/game";

export interface SocketEvents {
  // 客户端发送的事件
  "join-room": (data: { roomId: string; playerName: string }) => void;
  "leave-room": (data: { roomId: string }) => void;
  "draw-stroke": (data: { roomId: string; stroke: DrawStroke }) => void;
  "clear-canvas": (data: { roomId: string }) => void;
  "guess-word": (data: {
    roomId: string;
    guess: string;
    playerId: string;
  }) => void;
  "start-game": (data: {
    roomId: string;
    config?: { roundTime?: number; wordBankId?: string };
  }) => void;

  // 服务器发送的事件
  "room-joined": (data: {
    success: boolean;
    playerId: string;
    gameState: GameState;
  }) => void;
  "player-joined": (data: { player: Player; players: Player[] }) => void;
  "player-left": (data: { playerId: string; players: Player[] }) => void;
  "game-state-updated": (data: { gameState: Partial<GameState> }) => void;
  "stroke-received": (data: { stroke: DrawStroke }) => void;
  "stroke-undone": () => void;
  "canvas-cleared": () => void;
  "guess-received": (data: {
    playerId: string;
    playerName: string;
    guess: string;
    isCorrect: boolean;
  }) => void;
  "game-started": (data: { gameState: GameState }) => void;
  "round-ended": (data: {
    correctWord: string;
    scores: Record<string, number>;
  }) => void;
  error: (data: { message: string }) => void;
}

export class WebSocketService {
  private socket: Socket | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectDelay = 1000;

  // constructor(private serverUrl = "http://draw-guess.bdow.com.cn:3001") {}
  constructor() {}

  connect(): Promise<Socket> {
    return new Promise((resolve, reject) => {
      if (this.socket?.connected) return resolve(this.socket);

      this.socket = io("/", {
        // ✅ 同域
        path: "/socket.io",
        transports: ["websocket", "polling"],
        timeout: 5000,
        forceNew: true,
        withCredentials: true,
      });

      this.socket.on("connect", () => {
        this.reconnectAttempts = 0;
        resolve(this.socket!);
      });
      this.socket.on("connect_error", (err) => {
        this.handleReconnect();
        reject(err);
      });
      this.socket.on("disconnect", (reason) => {
        if (reason === "io server disconnect") this.handleReconnect();
      });
    });
  }

  private handleReconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      console.log(
        `尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`
      );

      setTimeout(() => {
        this.connect().catch(console.error);
      }, this.reconnectDelay * this.reconnectAttempts);
    } else {
      console.error("重连失败，已达到最大重连次数");
    }
  }

  disconnect() {
    if (this.socket) {
      this.socket.disconnect();
      this.socket = null;
    }
  }

  // 事件发送方法
  joinRoom(roomId: string, playerName: string) {
    this.socket?.emit("join-room", { roomId, playerName });
  }

  leaveRoom(roomId: string) {
    this.socket?.emit("leave-room", { roomId });
  }

  sendStroke(roomId: string, stroke: DrawStroke) {
    this.socket?.emit("draw-stroke", { roomId, stroke });
  }

  clearCanvas(roomId: string) {
    this.socket?.emit("clear-canvas", { roomId });
  }

  sendGuess(roomId: string, guess: string, playerId: string) {
    this.socket?.emit("guess-word", { roomId, guess, playerId });
  }

  startGame(
    roomId: string,
    config?: { roundTime?: number; wordBankId?: string }
  ) {
    this.socket?.emit("start-game", { roomId, config });
  }

  // 事件监听方法
  onRoomJoined(
    callback: (data: {
      success: boolean;
      playerId: string;
      gameState: GameState;
    }) => void
  ) {
    this.socket?.on("room-joined", callback);
  }

  onPlayerJoined(
    callback: (data: { player: Player; players: Player[] }) => void
  ) {
    this.socket?.on("player-joined", callback);
  }

  onPlayerLeft(
    callback: (data: { playerId: string; players: Player[] }) => void
  ) {
    this.socket?.on("player-left", callback);
  }

  onGameStateUpdated(
    callback: (data: { gameState: Partial<GameState> }) => void
  ) {
    this.socket?.on("game-state-updated", callback);
  }

  onStrokeReceived(callback: (data: { stroke: DrawStroke }) => void) {
    this.socket?.on("stroke-received", callback);
  }

  onCanvasCleared(callback: () => void) {
    this.socket?.on("canvas-cleared", callback);
  }

  onGuessReceived(
    callback: (data: {
      playerId: string;
      playerName: string;
      guess: string;
      isCorrect: boolean;
    }) => void
  ) {
    this.socket?.on("guess-received", callback);
  }

  onGameStarted(callback: (data: { gameState: GameState }) => void) {
    this.socket?.on("game-started", callback);
  }

  onRoundEnded(
    callback: (data: {
      correctWord: string;
      scores: Record<string, number>;
    }) => void
  ) {
    this.socket?.on("round-ended", callback);
  }

  onGameFinished(callback: (data: { scores: Record<string, number> }) => void) {
    this.socket?.on("game-finished", callback);
  }

  onError(callback: (data: { message: string }) => void) {
    this.socket?.on("error", callback);
  }

  // 移除事件监听
  off(event: string, callback?: (...args: any[]) => void) {
    this.socket?.off(event, callback);
  }

  // 获取连接状态
  get isConnected(): boolean {
    return this.socket?.connected || false;
  }

  // 获取socket实例
  get socketInstance(): Socket | null {
    return this.socket;
  }
}

// 单例模式
export const websocketService = new WebSocketService();
